#include "ProxyServerToWorldModule.h"
#include "ProxyServerNetClientPlugin.h"
#include "Protocol/Protocol.h"

bool FragrantGrass::ProxyServerToWorldModule::Init()
{
	m_pSecurityModule = m_pPluginManager->FindModule<ISecurityModule>();
	m_pProxyLogicModule = m_pPluginManager->FindModule<IProxyLogicModule>();
	m_pProxyServerNet_ServerModule = m_pPluginManager->FindModule<IProxyServerNetServerModule>();
	m_pLogModule = m_pPluginManager->FindModule<ILogModule>();
	m_pNetClientModule = m_pPluginManager->FindModule<INetClientModule>();
	m_pConfigModule = m_pPluginManager->FindModule<IConfigModule>();

    return true;
}

bool FragrantGrass::ProxyServerToWorldModule::Shut()
{
    //Final();
    //Clear();
    return true;
}

bool FragrantGrass::ProxyServerToWorldModule::Execute()
{
	ServerReport();
	return true;
}

void FragrantGrass::ProxyServerToWorldModule::OnServerInfoProcess(const SOCK nSockIndex, const int nMsgID, const char* msg, const uint32_t nLen)
{
    GUID nPlayerID;
    Protocol::ServerInfoReportList xMsg;
    if (!INetModule::recieve_protobuf_message( nMsgID, msg, nLen, xMsg, nPlayerID))
    {
        return;
    }

    for (int i = 0; i < xMsg.server_list_size(); ++i)
    {
        const Protocol::ServerInfoReport& xData = xMsg.server_list(i);

        //type
        ConnectData xServerData;

        xServerData.nGameID = xData.server_id();
        xServerData.strIP = xData.server_ip();
        xServerData.nPort = xData.server_port();
        xServerData.strName = xData.server_name();
		xServerData.nWorkLoad = xData.server_cur_count();
        xServerData.eServerType = (FG_SERVER_TYPES)xData.server_type();

        switch (xServerData.eServerType)
        {
            case FG_SERVER_TYPES::FG_ST_GAME:
            {
                m_pNetClientModule->AddServer(xServerData);
            }
            break;
            case FG_SERVER_TYPES::FG_ST_WORLD:
            {
				m_pNetClientModule->AddServer(xServerData);
            }
            break;
            default:
                break;
        }

    }
}

void FragrantGrass::ProxyServerToWorldModule::OnSocketWorldServerEvent(const SOCK nSockIndex, const FG_NET_EVENT eEvent, INet* pNet)
{
    if (eEvent & FG_NET_EVENT_EOF)
    {
        m_pLogModule->LogNormal(ILogModule::LL_INFO_NORMAL, GUID(0, nSockIndex), "FG_NET_EVENT_EOF", "Connection closed", __FUNCTION__, __LINE__);
    }
    else if (eEvent & FG_NET_EVENT_ERROR)
    {
        m_pLogModule->LogNormal(ILogModule::LL_INFO_NORMAL, GUID(0, nSockIndex), "FG_NET_EVENT_ERROR", "Got an error on the connection", __FUNCTION__, __LINE__);
    }
    else if (eEvent & FG_NET_EVENT_TIMEOUT)
    {
        m_pLogModule->LogNormal(ILogModule::LL_INFO_NORMAL, GUID(0, nSockIndex), "FG_NET_EVENT_TIMEOUT", "read timeout", __FUNCTION__, __LINE__);
    }
    else  if (eEvent & FG_NET_EVENT_CONNECTED)
    {
        m_pLogModule->LogNormal(ILogModule::LL_INFO_NORMAL, GUID(0, nSockIndex), "FG_NET_EVENT_CONNECTED", "connected success", __FUNCTION__, __LINE__);
        Register(pNet);
    }
}

void FragrantGrass::ProxyServerToWorldModule::Register(INet* pNet)
{
	const Protocol::ServerInfoReportList& serverInfoList = *(const Protocol::ServerInfoReportList*)m_pConfigModule->GetConfigDatas(IConfigModule::FileParseType::FPT_SERVER_DATA);
	int n = serverInfoList.server_list_size();
	const int nCurAppID = m_pPluginManager->GetAppID();
	bool hasWorldServer = false;
	for (int i = 0; i < n; ++i)
	{
		const Protocol::ServerInfoReport& serverInfo = serverInfoList.server_list(i);
		const int nServerType = serverInfo.server_type();
		const int nServerID = serverInfo.server_id();
		if (nServerType == FG_SERVER_TYPES::FG_ST_PROXY && nCurAppID == nServerID)
		{
			const int nPort = serverInfo.server_port();
			const int nMaxConnect = serverInfo.server_max_online();
			const int nCpus = serverInfo.server_cur_count();
			const std::string& strName = serverInfo.server_name();
			const std::string& strIP = serverInfo.server_ip();
			const int strId = serverInfo.server_id();

		    Protocol::ServerInfoReportList xMsg;
		    Protocol::ServerInfoReport* pData = xMsg.add_server_list();

		    pData->set_server_id(nServerID);
		    pData->set_server_name(lexical_cast<std::string>(strId));
		    pData->set_server_cur_count(0);
		    pData->set_server_ip(strIP);
		    pData->set_server_port(nPort);
		    pData->set_server_max_online(nMaxConnect);
		    pData->set_server_state(Protocol::EST_NARMAL);
		    pData->set_server_type(nServerType);

		    FG_SHARE_PTR<ConnectData> pServerData = GetClusterModule()->GetServerNetInfo(pNet);
		    if (pServerData)
		    {
		        int nTargetID = pServerData->nGameID;
				GetClusterModule()->SendToServerByPB(nTargetID, Protocol::EGameMsgID::EGMI_PTWG_PROXY_REGISTERED, xMsg);

		        m_pLogModule->LogNormal(ILogModule::LL_INFO_NORMAL, GUID(0, pData->server_id()), pData->server_name(), "ready to registe to world server");
		    }
		}
	}
}

void FragrantGrass::ProxyServerToWorldModule::ServerReport()
{
	if (mLastReportTime + 10 > m_pPluginManager->GetNowTime())
	{
		return;
	}
	mLastReportTime = m_pPluginManager->GetNowTime();

	const Protocol::ServerInfoReportList& serverInfoList = *(const Protocol::ServerInfoReportList*)m_pConfigModule->GetConfigDatas(IConfigModule::FileParseType::FPT_SERVER_DATA);
	int n = serverInfoList.server_list_size();
	const int nCurAppID = m_pPluginManager->GetAppID();
	for (int i = 0; i < n; ++i)
	{
		const Protocol::ServerInfoReport& serverInfo = serverInfoList.server_list(i);
		const int nServerType = serverInfo.server_type();
		const int nServerID = serverInfo.server_id();

		if (nServerID == nCurAppID && nServerType == (int)FG_SERVER_TYPES::FG_ST_PROXY)
		{
			const int nPort = serverInfo.server_port();
			const int nMaxConnect = serverInfo.server_max_online();
			const int nCpus = serverInfo.server_cur_count();
			const std::string& strName = serverInfo.server_name();
			const std::string& strIP = serverInfo.server_ip();
			const int strId = serverInfo.server_id();

			Protocol::ServerInfoReport reqMsg;

			reqMsg.set_server_id(nServerID);
			reqMsg.set_server_name(lexical_cast<std::string>(strId));
   			reqMsg.set_server_cur_count(0);
   			reqMsg.set_server_ip(strIP);
   			reqMsg.set_server_port(nPort);
   			reqMsg.set_server_max_online(nMaxConnect);
   			reqMsg.set_server_state(Protocol::EST_NARMAL);
   			reqMsg.set_server_type(nServerType);

#ifdef FG_DEBUG_MODE
			printf("[Send]:ProxyServerToWorldModule::ServerReport %s id=%d\n", ServerData::get_server_type_name(reqMsg.server_type()), reqMsg.server_id());
#endif
   			m_pNetClientModule->SendToAllServerByPB(FG_SERVER_TYPES::FG_ST_WORLD, Protocol::EGMI_STS_SERVER_REPORT, reqMsg);
		}
	}
}

bool FragrantGrass::ProxyServerToWorldModule::AfterInit()
{
	m_pNetClientModule->AddReceiveCallBack(FG_SERVER_TYPES::FG_ST_WORLD, Protocol::EGMI_ACK_CONNECT_WORLD, this, &FragrantGrass::ProxyServerToWorldModule::OnSelectServerResultProcess);
	m_pNetClientModule->AddReceiveCallBack(FG_SERVER_TYPES::FG_ST_WORLD, Protocol::EGMI_STS_NET_INFO, this, &FragrantGrass::ProxyServerToWorldModule::OnServerInfoProcess);
	m_pNetClientModule->AddReceiveCallBack(FG_SERVER_TYPES::FG_ST_WORLD, this, &FragrantGrass::ProxyServerToWorldModule::OnOtherMessage);

	m_pNetClientModule->AddEventCallBack(FG_SERVER_TYPES::FG_ST_WORLD, this, &FragrantGrass::ProxyServerToWorldModule::OnSocketWorldServerEvent);
	m_pNetClientModule->ExpandBufferSize();

	const Protocol::ServerInfoReportList& serverInfoList = *(const Protocol::ServerInfoReportList*)m_pConfigModule->GetConfigDatas(IConfigModule::FileParseType::FPT_SERVER_DATA);
	int n = serverInfoList.server_list_size();
	const int nCurAppID = m_pPluginManager->GetAppID();
	bool hasTheSameAppIdServer = false;
	for (int i = 0; i < n; ++i)
	{
		const Protocol::ServerInfoReport& serverInfo = serverInfoList.server_list(i);
		const int nServerType = serverInfo.server_type();
		const int nServerID = serverInfo.server_id();
		if (nServerID == nCurAppID)
		{
			hasTheSameAppIdServer = true;
			break;
		}
	}

	if (!hasTheSameAppIdServer)
	{
		std::ostringstream strLog;
		strLog << "Cannot find current server, AppID = " << nCurAppID;
		m_pLogModule->LogNormal(ILogModule::LL_ERROR_NORMAL, NULL_OBJECT, strLog, __FUNCTION__, __LINE__);
		FGASSERT(-1, "Cannot find current server", __FILE__, __FUNCTION__);
		exit(0);
	}

	for (int i = 0; i < n; ++i)
	{
		const Protocol::ServerInfoReport& serverInfo = serverInfoList.server_list(i);
		const int nServerType = serverInfo.server_type();
		const int nServerID = serverInfo.server_id();
		if (nServerType == FG_SERVER_TYPES::FG_ST_WORLD/* && nCurArea == nServerArea*/)
		{
			const int nPort = serverInfo.server_port();
			const int nMaxConnect = serverInfo.server_max_online();
			const int nCpus = serverInfo.server_cur_count();
			const std::string& strName = serverInfo.server_name();
			const std::string& strIP = serverInfo.server_ip();
			const int strId = serverInfo.server_id();

			ConnectData xServerData;
			xServerData.nGameID = nServerID;
			xServerData.eServerType = (FG_SERVER_TYPES)nServerType;
			xServerData.strIP = strIP;
			xServerData.nPort = nPort;
			xServerData.strName = lexical_cast<std::string>(strId);

			m_pNetClientModule->AddServer(xServerData);
		}
	}

    return true;
}


void FragrantGrass::ProxyServerToWorldModule::OnSelectServerResultProcess(const SOCK nSockIndex, const int nMsgID, const char* msg, const uint32_t nLen)
{
    GUID nPlayerID;
    Protocol::AckConnectWorldResult xMsg;
    if (!INetModule::recieve_protobuf_message( nMsgID, msg, nLen, xMsg, nPlayerID))
    {
        return;
    }

	auto& pConnectData = mWantToConnectMap[xMsg.account()];
	if (!pConnectData)
	{
		pConnectData = FG_SHARE_PTR<ClientConnectData>(FG_NEW ClientConnectData());
	}
    pConnectData->strAccount = xMsg.account();
    pConnectData->strConnectKey = xMsg.world_key();
}

FragrantGrass::INetClientModule* FragrantGrass::ProxyServerToWorldModule::GetClusterModule()
{
	return m_pNetClientModule;
}

bool FragrantGrass::ProxyServerToWorldModule::VerifyConnectData(const std::string& strAccount, const std::string& strKey)
{
	ClientConnectMap::iterator it = mWantToConnectMap.find(strAccount);
	if (it != mWantToConnectMap.end() && it->second && it->second->strConnectKey == strKey)
	{
		mWantToConnectMap.erase(it);
		return true;
	}

    return false;
}

void FragrantGrass::ProxyServerToWorldModule::LogServerInfo(const std::string& strServerInfo)
{
    m_pLogModule->LogNormal(ILogModule::LL_INFO_NORMAL, GUID(), strServerInfo, "");
}

void FragrantGrass::ProxyServerToWorldModule::OnOtherMessage(const SOCK nSockIndex, const int nMsgID, const char * msg, const uint32_t nLen)
{
	m_pProxyServerNet_ServerModule->Transpond(nSockIndex, nMsgID, msg, nLen);
}
